package mianshi;

public class ThreadText {
/*
              volatile可以保证可见性和有序性，但是不能保证原子性
      什么是可见性？
          可见性是由java内存模型造成的，对象的共享变量会保存在主内存之中，每个线程都有自己的工作内存，
          每个线程不能直接操作主内存中的共享变量，每个线程只能操作自己的工作内存中的共享变量副本。正是因为如此，
          当一个线程修改了共享变量之后，对于其他线程不是立即可见的，就会导致脏读的情况。
          而被volatile修饰的共享变量在被修改之后，会使其他线程工作内存中的共享变量的值无效化，并且将修改后的值刷新到主内存中，
          当其他线程再使用该共享变量时，必须要从主内存中读取。这样也就保证了可见性。
      什么是有序性？
           java文件在编译成字节码的时候，为了加快程序运行的效率，会对指令进行重排序，重排序执行程序的运行顺序(在保证结果一致
           的前提下)会被改变，重排序在串行的情况下不会有问题，但在并发的情况下，会导致线程安全问题。
           而被volatile修饰的变量会禁止指令的重排序。从而保证了有序性。

       使用场景：
            具有原子性操作的变量，配合Atomic*** 原子类一起使用
        优点：
            轻量级的处理线程安全的方式，效率要快于synchronized,因为不需要加锁
        缺点：
            不能保证原子性，只能适用于部分情况

           synchronized如何保证线程安全？
       原理：
            被synchronized修饰的方法，代码块，在编译之后会包含有monitorenter和monitorexit指令，
            这两个指令分别代表加锁和解锁。被这两个指令包含的部分在运行时是串行的，即在同一时间内只有一个线程能执行这部分的代码。
            串行不会存在原子性和有序性的问题。
      那么，synchronized如何保证可见性呢？
            在执行到monitorexit指令（解锁指令）时，会将工作线程中的共享变量的值刷新到主内存中，类似与volatile的操作，
            从而保证了共享变量的可见性

        CAS算法：
            conpare and swap 比较并替换。使用cas更改变量的值时，会将当前值与内存中的值进行比较，
            如果一样，则将内存中的值更新为新的值，如果不一样，则将当前值更新为最新的内存值，再继续重试。
            这一部分的操作是具有原子性的

        创建线程的方式
            1.Thread类
            2.Runnable接口，没有返回值
            3.Callable接口，有返回值
            4.线程池


        线程的生命周期


        终止线程的方式
            1.stop方法
                stop方法会立即中断线程，不会执行run中被中断之后的代码，这样会导致线程不安全。
                stop方法会释放该线程拥有的全部的锁，这样会导致同步代码块还未执行完，锁就被释放了，从而也会引发线程安全问题。
            2.interrupt方法
                interrupt方法不会立即中断线程，它只是通知线程要中断了，但是线程中断的时间是不确定的。因此，interrupt方法要搭配
                isInterrupted方法一起使用，当线程执行interrupt方法时，isInterrupt方法会返回ture，可通过该方法来判断线程是否被
                中断，从而执行线程中断后的业务逻辑。


        sleep和wait的区别
            1.sleep是Thread类的方法，而wait是Object类的方法
            2.sleep不会释放锁资源，而wait方法会释放锁资源
            3.wait方法要释放锁资源，因此必须要在被synchronized修饰的同步代码中，而sleep不会有这种限制
            4.sleep不需要被唤醒，当经过指定的时间之后，会自动唤醒并继续执行之后的代码，而wait方法需要notify或者notifyAll方法唤醒才能继续执行


        start和run的区别
            start方法会新开一个线程，并执行run方法
            run方法则是普通的方法，直接调用run方法时不会新开线程


        什么是守护线程？什么是用户线程？
            用户线程就是我们平常新创建的线程



        什么是线程安全?


        如何保证线程安全?


        java有几种锁?


        ReentrantLock和synchronized的区别


        锁升级的过程


        偏向锁,乐观锁,悲观锁,公平锁,非公平锁


        锁粗化和锁消除


        线程池的作用以及实现原理


    ThreadLocal

        ThreadLocal作用
            给每个线程都提供一个共享变量的变量副本，将共享变量都保存到每个Thread类的threadLocals中，每个线程只能操作自己Thread
            类中的变量，当线程对变量进行修改时，不会影响到其他线程中变量的值，从而保证线程安全。

        适用场景：
            业务逻辑不依赖该共享变量的时候，比如数据库连接池，session连接池
            因为被threadLocal包装的变量，在某个线程被修改之后，对于其他线程是不可见的，如果业务逻辑强烈依赖于该共享变量，则会导致
            可见性的问题，从而导致线程安全问题。

        内存泄漏
            threadLocalMap中的key是弱引用的，在下一次gc之前会被回收掉，但是value还存在map的强引用，
            因此不会被回收掉，但是又无法通过key访问到，因此，就导致了内存的泄露。只有当线程执行结束后，value才会被回收掉。

            如果threadLocal外部强引用被置为null(threadLocalInstance=null)的话，threadLocal实例
            就没有一条引用链路可达，很显然在gc(垃圾回收)的时候势必会被回收，因此entry就存在key为null的情况，
            无法通过一个Key为null去访问到该entry的value。同时，就存在了这样一条引用链：threadRef->currentThread->
            threadLocalMap->entry->valueRef->valueMemory,导致在垃圾回收的时候进行可达性分析的时候,value可达从而不会
            被回收掉，但是该value永远不能被访问到，这样就存在了内存泄漏。当然，如果线程执行结束后，threadLocal，
            threadRef会断掉，因此threadLocal,threadLocalMap，entry都会被回收掉。可是，在实际使用中我们都是会用
            线程池去维护我们的线程，比如在Executors.newFixedThreadPool()时创建线程的时候，为了复用线程是不会结束的，
            所以threadLocal内存泄漏就值得我们关注

        为什么使用弱引用的key?
            因为threadLocal对象被threadLocal的引用以及threadLocalMap强引用，即使将threadLocal引用置为null,
            由gc的可达性分析算法，threadLocal对象还是可以通过threadLocalMap可达的，因此无法被gc回收。这样会导致逻辑错误。
             而使用弱引用的key，在下一次gc之前，threadLocal对象会被回收，这也导致了threadLocalMap中的key为null，从而导致了
             value的内存泄露。即使会导致value的内存泄露，在threadLocalMap的生命周期中，执行set,get,remove方法的时候，都会对
             key为null的value进行清理。解决了value内存泄漏的问题。

         ThreadLocal对弱引用key的优化：
            执行get,set,remove方法的时候，会对key为null的键值对进行清理

        正确使用threadLocal
            每次使用完threadLocal，都调用它的remove方法，清除value的值


        什么是AQS


        阻塞队列的原理


        CyclicBarrier,CountDownLatch,Semaphore是什么,有什么用,用法及区别




 */
}
